Closure란 무엇인가?
A closure is a function plus a connection to the variables that exist at its “birth place”.
2가 왜 필요할까? 👀 [[JavaScript - Call, Apply, Bind]]
function hello(parentVar) {
return function (childVar) {
console.log(`${parentVar} -> ${childVar}`)
}
}
const world = hello("1") // 내부 함수 생성시에 전달된 변수를 계속 알고있다.
world("2") // `1 -> 2`
hello
함수는 world
에 closure를 반환한다.
world
는 할당될 때 알고있던 값을 계속 알 수 있기 때문에 함수 호출이 끝나서 함수의 Scope를 벗어났음에도 인자 parentVar
에 전달한 값 "1"
에 대해 알고 있다.
언제 사용할까?
예제를 보자.
class Countdown {
constructor(counter, action) {
Object.assign(this, {
dec() {
if (counter < 1) return
counter--
if (counter === 0) {
action()
}
},
})
}
}
clousure의 장점 - 일단 이런식으로 은닉화 하는 것은 코드를 이해하기 힘듦. 그래서 #private
같은 syntactic sugar가 추가되는 것 같다. - 부분 적용 함수를 만들 수 있다. 함수의 확장에 용이함.
단점 - 루프 안에서 외부 scope의 변수/함수를 참조하는 경우, clousre때문에 같은 [[JavaScript - lexical environment]]를 공유하기 때문에 실수할 수 있다.
function showHelp(help) {
document.getElementById("help").textContent = help
}
function setupHelp() {
var helpText = [
{ id: "email", help: "Your e-mail address" },
{ id: "name", help: "Your full name" },
{ id: "age", help: "Your age (you must be over 16)" },
]
for (var i = 0; i < helpText.length; i++) {
// var는 함수 내에서 hoisting되어,
// 다음 함수에서 하나의 lexical environment로 참조되고
// 결국 함수 호출 시점에는, 마지막 값인 'age'만 사용됨.
var item = helpText[i]
document.getElementById(item.id).onfocus = function () {
showHelp(item.help)
}
}
}
setupHelp()
function MyObject(name, message) {
this.name = name.toString()
this.message = message.toString()
this.getName = function () {
return this.name
}
this.getMessage = function () {
// 안에서 이렇게 하기보다 prototype에..
return this.message
}
}